﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using UMLTouch.Domain.ClassDiagram.Items;
using UMLTouch.Core.UI;


namespace UMLTouch.Domain.ClassDiagram.Controls
{
    /// <summary>
    /// Interaction logic for RelationArrowControl.xaml
    /// </summary>
    public partial class RelationArrowControl : UserControl, IAnchorable
    {

        ItemAnchor _startAnchor;
        ItemAnchor _endAnchor;

        List<ItemAnchor> _anchors;
        List<IAnchorable> _anchored;

        RelationArrowItem _item;


        public RelationArrowControl()
        {
            InitializeComponent();
        }

        public RelationArrowControl(RelationArrowItem item)
            :this()
        {
            _item = item;
            

            //arrowLine.X1 = _item.Start.X;
            //arrowLine.Y1 = _item.Start.Y;
            //arrowLine.X2 = _item.End.X;
            //arrowLine.Y2 = _item.End.Y;

            _anchored = new List<IAnchorable>();
            _anchors = new List<ItemAnchor>();
            _startAnchor = new ItemAnchor(this, ItemAnchorDirection.Single, item.Start);//new Point((_item.Position.X + _item.Start.X), (_item.Position.Y + _item.Start.Y)));
            _startAnchor.AnchorMoved += new EventHandler(Anchor_AnchorMoved);
            _endAnchor = new ItemAnchor(this, ItemAnchorDirection.Single, item.End);//new Point((_item.Position.X + _item.End.X),(_item.Position.Y + _item.End.Y)));
            _endAnchor.AnchorMoved += new EventHandler(Anchor_AnchorMoved);

            _anchors.Add(_startAnchor);
            _anchors.Add(_endAnchor);

            DrawLine();
        }

        void Anchor_AnchorMoved(object sender, EventArgs e)
        {

            DrawLine();
        }



        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            //SetValue(InkCanvas.LeftProperty, _item.Position.X);
            //SetValue(InkCanvas.TopProperty, _item.Position.Y);
            SetValue(Panel.ZIndexProperty, 0);


        }

        void DrawLine()
        {
            c_content.Children.Clear();

            var StartConnected = _startAnchor.ConnectedAnchors.FirstOrDefault();
            ItemAnchorDirection directionStart;

            if (StartConnected != null)
            {
                directionStart = StartConnected.Direction;
            }
            else
            {
                directionStart = ItemAnchorDirection.Single;
            }



            var EndConnected = _endAnchor.ConnectedAnchors.FirstOrDefault();
            ItemAnchorDirection directionEnd;

            if (EndConnected != null)
            {
                directionEnd = EndConnected.Direction;
            }
            else
            {
                directionEnd = ItemAnchorDirection.Single;
            }

            Vector delta = new Vector()
            {   
                X = Math.Abs(_startAnchor.Position.X - _endAnchor.Position.X),
                Y = Math.Abs(_startAnchor.Position.Y - _endAnchor.Position.Y)
            };


            Point p1 = new Point();
            switch (directionStart)
            {
                case ItemAnchorDirection.Top:
                    p1.X = _startAnchor.Position.X;
                    p1.Y = (_startAnchor.Position.Y - 30);
                    break;
                case ItemAnchorDirection.Bottom:
                    p1.X = _startAnchor.Position.X;
                    p1.Y = (_startAnchor.Position.Y + 30 );
                    break;
                case ItemAnchorDirection.Left:
                    p1.X = _startAnchor.Position.X - 30;
                    p1.Y = (_startAnchor.Position.Y);
                    break;
                case ItemAnchorDirection.Right:
                    p1.X = _startAnchor.Position.X + 30;
                    p1.Y = (_startAnchor.Position.Y);
                    break;
                case ItemAnchorDirection.Single:
                    break;
                default:
                    break;
            }

            Point p2 = new Point();
            switch (directionEnd)
            {
                case ItemAnchorDirection.Top:
                    p2.X = _endAnchor.Position.X;
                    p2.Y = (_endAnchor.Position.Y - 30);
                    break;
                case ItemAnchorDirection.Bottom:
                    p2.X = _endAnchor.Position.X;
                    p2.Y = (_endAnchor.Position.Y + 30);
                    break;
                case ItemAnchorDirection.Left:
                    p2.X = _endAnchor.Position.X  - 30;
                    p2.Y = (_endAnchor.Position.Y);
                    break;
                case ItemAnchorDirection.Right:
                    p2.X = _endAnchor.Position.X + 30;
                    p2.Y = (_endAnchor.Position.Y);
                    break;
                case ItemAnchorDirection.Single:
                    break;
                default:
                    break;
            }

            if (directionEnd != ItemAnchorDirection.Single && directionStart != ItemAnchorDirection.Single)
            {
                DrawLine(_startAnchor.Position, p1);
                DrawLine(p1, p2);
                DrawLine(p2, _endAnchor.Position);
            }
            else
            {
                DrawLine(_startAnchor.Position, _endAnchor.Position);
            }
        }

        void DrawLine(Point p1, Point p2)
        {
            Line l = new Line();
            l.Stroke = Brushes.Gray;
            l.Effect = new System.Windows.Media.Effects.DropShadowEffect()
            {
                BlurRadius = 5,
                Color = Colors.DarkGray
            };
            l.X1 = p1.X;
            l.X2 = p2.X;
            l.Y1 = p1.Y;
            l.Y2 = p2.Y;

            c_content.Children.Add(l);
        }


        #region IAnchorable Members

        public IEnumerable<ItemAnchor> Anchors
        {
            get { return _anchors; }
        }

        public IEnumerable<IAnchorable> AnchoredItems
        {
            get { return _anchored; }
        }

        public Boolean ConnectItem(IAnchorable item)
        {
            #region Old
            var anchorsPairs = (from thisAnc in _anchors
                                from destAnc in item.Anchors
                                let dist = Math.Abs((thisAnc.Position - destAnc.Position).Length)
                                where dist <= 40
                                group new { destAnc, dist } by thisAnc

                               );


            Boolean ret = false;

            foreach (var group in anchorsPairs)
            {
                var bestDestination = group.OrderBy(gp => gp.dist).FirstOrDefault();
                if (bestDestination != null)
                {
                    group.Key.ConnectedAnchors.Add(bestDestination.destAnc);
                    bestDestination.destAnc.ConnectedAnchors.Add(group.Key);
                    group.Key.Position = bestDestination.destAnc.Position;
                    ret = true;
                }
            }

            return ret;
            #endregion




        }
        #endregion

        #region IAnchorable Members


        public void Move(Vector move)
        {
            foreach (var item in _anchors)
            {
                item.Position += move;
            }
        }

        #endregion
    }
}
